fix: route proxy OAuth flow through proxy fetch to bypass CORS - #1638
fix: route proxy OAuth flow through proxy fetch to bypass CORS#1638c-bik wants to merge 1 commit into
Conversation
When using Via Proxy connection mode, the browser-side token exchange POST to the OAuth token endpoint is CORS-blocked by corporate MCP gateways. Fix by: 1. OAuthCallback: pass createProxyFetch(config) as fetchFn to auth() when connectionType is "proxy", so the token exchange goes through the Node.js proxy instead of the browser. 2. useConnection: accept optional serverUrlOverride in connect() and use it for InspectorOAuthClientProvider, avoiding a React state timing race where sseUrl hasn't updated yet when connectMcpServer() is called from onOAuthConnect. 3. useConnection: remove authProvider from proxy transport options for SSE and Streamable HTTP. The token is injected manually via headers; having authProvider on a proxy-URL transport causes the SDK to do OAuth discovery against localhost:6277 on 401, triggering a bogus redirect to /authorize on the proxy. 4. App.tsx: pass connectionType and config to OAuthCallback, and forward serverUrl to connectMcpServer after OAuth callback.
|
Closing: v1 is deprecated. Thank you for this contribution, and apologies for the long wait for a response. v1 will receive security fixes only. We reviewed every open v1 PR for security impact before closing — see the backlog triage in #1819 — and a small number were retained for a final If the underlying problem still exists in v2, we'd genuinely like to know. Please open an issue describing it against v2. Note that we accept external contributions as issues rather than pull requests — maintainers handle design and implementation through a prompt-driven workflow. See Thanks again for taking the time to contribute to the Inspector. |
Summary
When using Via Proxy connection mode, the browser-side token exchange POST to the OAuth token endpoint is CORS-blocked by corporate MCP gateways (and any auth server that doesn't return
Access-Control-Allow-Originon POST responses). This causesTypeError: Failed to fetchafter the OAuth redirect completes, leaving the inspector unable to connect.This PR fixes three related failure modes in the proxy OAuth flow. It is related to #1342 (which fixes the same
OAuthCallbackCORS issue) but additionally addresses two further bugs that appear after the token exchange succeeds.Type of Change
Changes Made
OAuthCallback.tsx: acceptconfigandconnectionTypeprops; passcreateProxyFetch(config)asfetchFntoauth()whenconnectionType === "proxy", routing the token exchange through the Node.js proxy instead of the browser. This is the same pattern already used inuseConnection.handleAuthErrorandAuthDebugger.useConnection.ts- React state race fix:onOAuthConnectinApp.tsxcallssetSseUrl(serverUrl)immediately followed byconnectMcpServer(). BecausesetSseUrlis async,connectMcpServerstill sees the stalesseUrland looks up the OAuth token under the wrong sessionStorage key, finding nothing. Fixed by adding an optionalserverUrlOverrideparameter toconnect()and passing the URL directly fromonOAuthConnect.useConnection.ts- spurious redirect fix: In proxy mode,authProvider: serverAuthProviderwas passed toStreamableHTTPClientTransportandSSEClientTransport. When the transport receives a 401, the SDK callsauth()withserverUrlset to the proxy URL (localhost:6277/mcp), not the real MCP server. This causes OAuth discovery against the proxy, which returns 404, and the SDK then redirects the browser tolocalhost:6277/authorize. RemovedauthProviderfrom proxy transport options -- the Bearer token is already injected manually into headers before the connection is made.App.tsx: threadconnectionTypeandconfigdown toOAuthCallback; passserverUrlexplicitly toconnectMcpServerafter the OAuth callback.Related Issues
OAuthCallbackCORS fix; this PR adds fixes for two additional failure modes)Testing
Test Results and/or Instructions
Validated end-to-end against a real corporate MCP gateway backed by Azure AD, which enforces strict CORS on the token endpoint.
Without this fix:
/oauth/callbackTypeError: Failed to fetch(CORS-blocked)connectMcpServerreads the wrong sessionStorage keylocalhost:6277/authorizeWith this fix:
npm test-> 535/535 passnpm run test:e2e-> 24/24 passnpm run prettier-check-> passes on all changed filesChecklist
npm run prettier-fix)Breaking Changes
None.
OAuthCallbackgains two optional props; the single call site inApp.tsxis updated. Theconnect()signature change is additive (optional third parameter).Additional Context
The three bugs form a cascade: fix (1) alone and you hit (2); fix (1) and (2) and you hit (3). All three need to be addressed together for the proxy OAuth flow to work reliably against real-world auth servers with strict CORS policies.